Skip to main content

iFrame Integration Guide

This document will guide you on how to correctly integrate the Connected Payments iFrame to begin accepting payments.

Icon
Before you begin

What you'll need:

  • configId - Your iFrame configuration ID
  • userName - Your Connected Payments username with transaction permissions
  • secretKey - Your shared secret key (for HMAC generation)
  • HTTPS-enabled website (for embedded iFrames)

Choose your integration:

  • Hosted iFrame - Full-page redirect for traditional checkout flows
  • Embedded iFrame - In-page payment form for seamless experiences

Code samples: Code samples within this document are provided for reference purposes only and are not intended for production use.


How it works

Flow:

  1. Customer initiates checkout on your site
  2. Your server generates HMAC-signed URL with payment parameters
  3. Connected Payments validates signature and renders secure payment form
  4. Customer enters payment details (card data never touches your server)
  5. Payment is processed through the payment network
  6. Result delivered via webhook (authoritative), redirect, or PostMessage

Quick start

Step 1: Generate HMAC signature

Every payment request requires a verifyMessage — an HMAC-SHA256 signature that proves the URL was created by your server and hasn't been tampered with. Connected Payments validates this on every request.

How to generate it:

  1. Collect the required parameters for your payment request (see the code examples below)
  2. Join each parameter as a key=value pair, separated by &
  3. Hash the resulting string using HMAC-SHA256 with your secretKey
  4. Append the output as verifyMessage to your iFrame URL
Server-side only

Never generate the verifyMessage in client-side code — doing so would expose your secretKey. Always perform this step on your server.

Node.js
const crypto = require("crypto");

// Required parameters
const params = {
configId: "5f06c5f5-d4cb-483b-b0b2-242f48516dc5",
userName: "merchant.iframes",
txnType: 1,
merchReference: "ORDER-12345",
amount: 1000, // cents
};

// Create parameter string
const paramString = `configId=${params.configId}&userName=${params.userName}&txnType=${params.txnType}&merchReference=${params.merchReference}&amount=${params.amount}`;

// Generate HMAC
const verifyMessage = crypto
.createHmac("sha256", process.env.CONNECTED_PAYMENTS_SECRET_KEY)
.update(paramString)
.digest("hex");
PHP
$params = [
'configId' => '5f06c5f5-d4cb-483b-b0b2-242f48516dc5',
'userName' => 'merchant.iframes',
'txnType' => 1,
'merchReference' => 'ORDER-12345',
'amount' => 1000
];

$paramString = http_build_query($params);
$verifyMessage = hash_hmac('sha256', $paramString, getenv('CONNECTED_PAYMENTS_SECRET_KEY'));
Python
import hmac
import hashlib
import os

params = {
'configId': '5f06c5f5-d4cb-483b-b0b2-242f48516dc5',
'userName': 'merchant.iframes',
'txnType': 1,
'merchReference': 'ORDER-12345',
'amount': 1000
}

param_string = '&'.join([f"{k}={v}" for k, v in params.items()])
verify_message = hmac.new(
os.getenv('CONNECTED_PAYMENTS_SECRET_KEY').encode(),
param_string.encode(),
hashlib.sha256
).hexdigest()
C#
using System.Security.Cryptography;
using System.Text;

string paramString = "configId=5f06c5f5-d4cb-483b-b0b2-242f48516dc5&userName=merchant.iframes&txnType=1&merchReference=ORDER-12345&amount=1000";

using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(Environment.GetEnvironmentVariable("CONNECTED_PAYMENTS_SECRET_KEY"))))
{
byte[] hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(paramString));
string verifyMessage = BitConverter.ToString(hash).Replace("-", "").ToLower();
}

Step 2: Build iFrame URL

The string can now be appended to either the ‘hosted’ or ‘embedded’ endpoints using a ‘?’.

const baseUrl =
"https://sandbox.connectedpayments.commbank.com.au/es-client-frontend/hosted";
const iframeUrl = `${baseUrl}?${paramString}&verifyMessage=${verifyMessage}`;
info

Your assembled URL will look like this for the Hosted Implementation:

https://sandbox.connectedpayments.commbank.com.au/es-client-frontend/hosted?configId=5f06c5f5-d4cb-483b-b0b2-242f48516dc5&userName=merchant.iframes&txnType=1&merchReference=ORDER-12345&amount=1000&verifyMessage=abc123def456...

Your assembled URL will look like this for the Embedded Implementation:

https://sandbox.connectedpayments.commbank.com.au/es-client-frontend/embedded?configId=5f06c5f5-d4cb-483b-b0b2-242f48516dc5&userName=merchant.iframes&txnType=1&merchReference=ORDER-12345&amount=1000&verifyMessage=abc123def456...

Step 3: Implement client

Choose how to display the payment form to your customers. Use the embedded iFrame for a seamless in-page experience, or redirect to the hosted page for a full-screen checkout flow.

Option A: Embedded iFrame

<iframe
id="connectedpayments-iframe"
src="YOUR_GENERATED_URL"
width="100%"
height="600px"
frameborder="0"
allow="payment"
>
</iframe>

Option B: Hosted (Redirect)

window.location.href = iframeUrl;

Step 4: Handle response

Set up a webhook endpoint to receive payment results from Connected Payments. This server-to-server notification is the most reliable way to process successful payments and update your order status.

// Webhook endpoint (recommended)
app.post("/webhook", express.json(), (req, res) => {
// Validate signature
if (!validateSignature(req.body, req.headers["x-signature"])) {
return res.status(401).send("Invalid signature");
}

// Process payment result
if (req.body.responseCode === "00") {
fulfillOrder(req.body.merchReference);
}

// Acknowledge receipt
res.status(200).send("OK");
});

Complete example

View full Node.js implementation
// server.js
const express = require("express");
const crypto = require("crypto");
const app = express();

const CONFIG = {
configId: "5f06c5f5-d4cb-483b-b0b2-242f48516dc5",
userName: "merchant.iframes",
secretKey: process.env.CONNECTED_PAYMENTS_SECRET_KEY,
baseUrl:
"https://sandbox.connectedpayments.commbank.com.au/es-client-frontend/hosted",
};

function generateIframeUrl(orderData) {
const params = {
configId: CONFIG.configId,
userName: CONFIG.userName,
txnType: 1,
merchReference: orderData.reference,
amount: orderData.amount,
};

// Add optional parameters
if (orderData.returnUrl) params.returnUrl = orderData.returnUrl;
if (orderData.email) params.email = orderData.email;

// Create parameter string (required params only)
const paramString = `configId=${params.configId}&userName=${params.userName}&txnType=${params.txnType}&merchReference=${params.merchReference}&amount=${params.amount}`;

// Generate HMAC
const verifyMessage = crypto
.createHmac("sha256", CONFIG.secretKey)
.update(paramString)
.digest("hex");

// Build complete URL
const urlParams = new URLSearchParams(params);
urlParams.append("verifyMessage", verifyMessage);

return `${CONFIG.baseUrl}?${urlParams.toString()}`;
}

// Payment page
app.get("/checkout/:orderId", async (req, res) => {
const order = await getOrder(req.params.orderId);

const iframeUrl = generateIframeUrl({
reference: `ORDER-${order.id}-${Date.now()}`,
amount: order.total * 100,
returnUrl: `${process.env.APP_URL}/payment/return`,
email: order.customerEmail,
});

res.render("checkout", { iframeUrl });
});

// Webhook handler
app.post("/webhook", express.json(), (req, res) => {
if (!validateSignature(req.body, req.headers["x-signature"])) {
return res.status(401).send("Invalid signature");
}

if (req.body.responseCode === "00") {
updateOrder(req.body.merchReference, "paid");
fulfillOrder(req.body.merchReference);
} else {
updateOrder(req.body.merchReference, "failed");
}

res.status(200).send("OK");
});

app.listen(3000);
View full PHP implementation
<?php
function generateIframeUrl($orderData) {
$config = [
'configId' => '5f06c5f5-d4cb-483b-b0b2-242f48516dc5',
'userName' => 'merchant.iframes',
'secretKey' => getenv('CONNECTED_PAYMENTS_SECRET_KEY'),
'baseUrl' => 'https://sandbox.connectedpayments.commbank.com.au/es-client-frontend/hosted'
];

$params = [
'configId' => $config['configId'],
'userName' => $config['userName'],
'txnType' => 1,
'merchReference' => $orderData['reference'],
'amount' => $orderData['amount']
];

$paramString = http_build_query($params);
$verifyMessage = hash_hmac('sha256', $paramString, $config['secretKey']);

$params['verifyMessage'] = $verifyMessage;
return $config['baseUrl'] . '?' . http_build_query($params);
}

$order = getOrder($_GET['orderId']);
$iframeUrl = generateIframeUrl([
'reference' => 'ORDER-' . $order['id'] . '-' . time(),
'amount' => $order['total'] * 100,
'returnUrl' => 'https://yoursite.com/payment/return',
'email' => $order['email']
]);
?>

<!DOCTYPE html>
<html>
<body>
<iframe src="<?php echo htmlspecialchars($iframeUrl); ?>" width="100%" height="600px"></iframe>
</body>
</html>
View full Python implementation
import hmac
import hashlib
from urllib.parse import urlencode
from flask import Flask, render_template
import os

app = Flask(__name__)

CONFIG = {
'config_id': '5f06c5f5-d4cb-483b-b0b2-242f48516dc5',
'user_name': 'merchant.iframes',
'secret_key': os.getenv('CONNECTED_PAYMENTS_SECRET_KEY'),
'base_url': 'https://sandbox.connectedpayments.commbank.com.au/es-client-frontend/hosted'
}

def generate_iframe_url(order_data):
params = {
'configId': CONFIG['config_id'],
'userName': CONFIG['user_name'],
'txnType': 1,
'merchReference': order_data['reference'],
'amount': order_data['amount']
}

param_string = '&'.join([f"{k}={v}" for k, v in params.items()])

verify_message = hmac.new(
CONFIG['secret_key'].encode(),
param_string.encode(),
hashlib.sha256
).hexdigest()

params['verifyMessage'] = verify_message
return f"{CONFIG['base_url']}?{urlencode(params)}"

@app.route('/checkout/<order_id>')
def checkout(order_id):
order = get_order(order_id)
iframe_url = generate_iframe_url({
'reference': f'ORDER-{order["id"]}-{int(time.time())}',
'amount': int(order['total'] * 100),
'email': order['email']
})
return render_template('checkout.html', iframe_url=iframe_url)

Handle responses

Server-to-server webhooks provide reliable, authoritative payment results.

How it works:

  1. Payment is processed
  2. Connected Payments sends an HTTPS POST to your notification endpoint
  3. Your server validates the signature and processes the result
  4. Your server responds with HTTP 200 to acknowledge receipt
View webhook implementation example
app.post("/webhook", express.json(), (req, res) => {
// 1. Validate signature
const signature = req.headers["x-signature"];
if (!isValidSignature(req.body, signature)) {
return res.status(401).end();
}

// 2. Process payment result
const { responseCode, merchReference, txnReference } = req.body;

if (responseCode === "00") {
// Payment successful
fulfillOrder(merchReference);
sendConfirmationEmail(merchReference);
} else {
// Payment failed
notifyCustomer(merchReference, "Payment declined");
}

// 3. Acknowledge receipt (must return 200)
res.status(200).send("OK");
});

Configuration: Webhooks are configured in your iFrame config. Contact CommBank Support to set up.

Response handling comparison

MethodUse CaseValidation
WebhookAuthoritative payment processingSignature required
RedirectImmediate user feedback (hosted)Signature required
PostMessageReal-time UI updates (embedded)Origin check only

Approach:

  1. Primary: Use webhooks/notifications for authoritative payment processing
  2. Secondary: Use redirects or PostMessages for immediate user feedback
  3. Always: Validate signatures on webhooks and redirects
  4. Never: Process orders based solely on PostMessages

Configuration reference

Environments

EnvironmentHosted URLEmbedded URL
Sandboxhttps://sandbox.connectedpayments.commbank.com.au/es-client-frontend/hostedhttps://sandbox.connectedpayments.commbank.com.au/es-client-frontend/embedded
Productionhttps://connectedpayments.commbank.com.au/es-client-frontend/hostedhttps://connectedpayments.commbank.com.au/es-client-frontend/embedded

Parameters

ParameterTypeDescriptionExample
configIdstringYour iFrame configuration ID. You can have multiple IDs for different use cases.'5f06c5f5-d4cb-483b-b0b2-242f48516dc5'
userNamestringConnected Payments username with transaction permissions'merchant.iframes'
txnTypeintegerTransaction type (see transaction types below)1
merchReferencestringUnique transaction reference — duplicates will be rejected'ORDER-12345'
amountintegerAmount in cents (e.g. 1000 = $10.00, 9999 = $99.99)1000
verifyMessagestringHMAC SHA-256 signature'abc123...'
info

For merchReference, use a format like ORDER-{orderId}-{timestamp} or a UUID to guarantee uniqueness.

Transaction types

ValueTypeDescription
1PurchaseStandard payment
9CaptureCapture pre-authorized funds
10Pre-AuthHold funds without charging
20RefundRefund against original transaction
21Open RefundRefund without original transaction
30VoidCancel transaction before settlement
39ReversalReverse a transaction

Testing

For test credentials, test cards, and integration verification steps, see the Testing Guide.